package com.quanfu.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 *         1.包扫描注解配置  @ComponentScan(value = "com.quanfu.ioc_01")
 *         2.引用外部的配置文件
 *         3.声明第三方依赖的bean组件
 *
 * 步骤一：添加@Configuration代表我们是配置类
 * 步骤二：实现上面的三个功能注解
 *
 */

@ComponentScan({"com.quanfu.ioc_01","com.quanfu.ioc_02"})
@PropertySource(value = "classpath:jdbc.properties")
@Configuration
public class JavaConfiguration {

    @Value("${quanfu.url}")
    private String url;
    @Value("${quanfu.username}")
    private String username;
    @Value("${quanfu.password}")
    private String password;
    @Value("${quanfu.driverClassName}")
    private String driverClassName;



    /**
     * <bean  -> 一个方法
     *
     * 方法的返回值类型 == bean组件的类型或者他的接口和父类
     * 方法的名字 = bean id
     * 方法体可以自定义实现过程即可
     *
     * 最重要一步：@Bean 会真正的让配置类的方法创建的组件存储到ioc容器
     *
     *
     * 问题一：beanName的问题
     *          默认：方法名
     *          指定：name / value 属性起名字，覆盖方法名
     * 问题二：周期方法如何制定
     *          原有注解方案： PostConstruct + PreDestroy
     *          bean属性指定
     * 问题三：作用域
     *        和以前一样 @Scope注解，默认是单例
     * 问题四：如何引用其他的ioc组件
     *        直接调用对方的bean方法即可
     *        直接形参变量进行引入，要求必须有对应的组件，如果有多个，形参名 = 组件id标识即可
     *
     *
     */
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean(name = "ergouzi")
    public DruidDataSource dataSource() {
        // 实现具体的实例化过程
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }


    // JdbcTemplate -> DataSource
    @Bean
    public JdbcTemplate jdbcTemplate() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        // 需要DataSource 需要ioc容器的其他组件
        // 方案一：如果其他组件也是@Bean方法，可以直接调用 | 从ioc容器获取组件
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }




    @Bean
    public JdbcTemplate jdbcTemplate1(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        // 需要DataSource 需要ioc容器的其他组件
        // 方案二：形参列表声明想要的组件类型，可以是一个也可以是多个！ ioc容器也会注入
        // 如果没有：形参变量注入，要求必须有对应的类型的组件，如果没有抛异常
        // 如果有多个：可以使用形参名称等同于对应的bean id 标识即可
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }


}
